<?php
require_once('exceptions/SurveysException.php');

class SurveysManager {
	
	public function __construct() {}
	
	/**
	 * 
	 */
	public function getSurveys($oUser) {
		try {
			return $oUser->surveys;
		} catch(Exception $e) {
			throw $e;
		}
	}
	
	/**
	 * 
	 */
	public function getSurveysAsArrays($oUser, $asStati) {
		try {
			$oSurveys = array();
		    foreach($oUser->surveys as $oSurvey) {
		        if(in_array($oSurvey->status, $asStati)) {
			        $oSurveys[] = $oSurvey->__toArray();
			    }
		    }
		    return $oSurveys;
		} catch(Exception $e) {
		    if($e instanceof Morph_Exception_ObjectNotFound)
		        throw new Exception("Ein Objekt wurde nicht gefunden");
			else
			    throw $e;
		}
	}
	
	/**
	 * 
	 */
	public function getSurvey($oUser, $sSurveyID) {
		try {
			foreach($oUser->surveys as $oSurvey) {
				if($oSurvey->id() == $sSurveyID)
					return $oSurvey;
			}
			throw new Exception("Befragung konnte nicht gefunden werden");
		} catch(Exception $e) {
			throw $e;
		}
	}

	/**
	 * 
	 */
	public function getSurveyAsArray($oUser, $sSurveyID) {		
		try {
			foreach($oUser->surveys as $oSurvey) {
				if($oSurvey->id() == $sSurveyID) {
					$oTempSurvey = $oSurvey->__toArray();
					
					$oTempSurvey['questionnaires'] = array();
					foreach($oUser->questionnaires as $oQuestionnaire) {
						$oTempSurvey['questionnaires'][] = array('title' => $oQuestionnaire->title,
															     '_id' => $oQuestionnaire->id());
				    }
			    	$oTempSurvey['questionnaire']->title = $oSurvey->questionnaireID->title;
			    	$oTempSurvey['questionnaire']->_id = $oSurvey->questionnaireID->id();
					return $oTempSurvey;
				}
			}
			throw new Exception("Befragung konnte nicht gefunden werden");
		} catch(Exception $e) {
			throw $e;
		}
	}

	/**
	 * 
	 */
	public function getNewSurveyAsArray($oUser) {		
		try {
			$oSurvey = new Survey();
			$oSurvey->creator = $oUser->firstName . " " . $oUser->lastName;
			$oSurvey->validFrom = date('d.m.Y', time());
			$oSurvey->validTo = date('d.m.Y', mktime(0, 0, 0, date("m"), date("d")+1, date("Y")));
			$oSurvey = $oSurvey->__toArray();
			$oSurvey['_id'] = "new";
			
			$oSurvey['questionnaires'] = array();
			foreach($oUser->questionnaires as $oQuestionnaire) {
				$oSurvey['questionnaires'][] = array('title' => $oQuestionnaire->title,
													 '_id' => $oQuestionnaire->id());
		    }
	    
			return $oSurvey;
		} catch(Exception $e) {
			throw $e;
		}
	}
	
	/**
	 * 
	 */
	public function getResult($oUser, $sSurveyID) {
		throw new SurveysException("Befragung konnte nicht gefunden werden.");
	}
	
	/**
	 * @todo kleiner und übersichtlicher machen
	 */
	public function saveSurvey($oUser, $asParams) {
        $mongo = new Mongo();
		Morph_Storage::init($mongo->selectDB('befragungssystem'));
		
		try {
			if($this->isSurveyDataPlausible($asParams)) {
				if($asParams['_id'] == "new") { // save a new survey
					$oSurvey = new Survey();
					$oSurvey = $this->setSurveyData($oSurvey, $asParams);
									
					$oUser->surveys[] = $oSurvey;
					$oUser->firstName = $oUser->firstName;
					$oUser->save();
				    $oSurvey->privateLink = "participation.php?#/participate/" . $oSurvey->id();
                    $oUser->firstName = $oUser->firstName;
                    $oUser->save();
				} else { // save an existing survey
					$oSurvey = $this->getSurvey($oUser, $asParams['_id']);
					$oSurvey = $this->setSurveyData($oSurvey, $asParams);
					$oSurvey->title = $oSurvey->title;
					$oSurvey->save();
				}
				
				$oTempSurvey = $oSurvey->__toArray();
				$oTempSurvey['questionnaires'] = array();
				foreach($oUser->questionnaires as $oQuestionnaire) {
					$oTempSurvey['questionnaires'][] = array('title' => $oQuestionnaire->title,
														     '_id' => $oQuestionnaire->id());
			    }
			    $oTempSurvey['questionnaire']->title = $oSurvey->questionnaireID->title;
			    $oTempSurvey['questionnaire']->_id = $oSurvey->questionnaireID->id();
				return $oTempSurvey;
			}			
		} catch(Exception $e) {
			throw $e;
		}
	}
	
	/**
	 * Loads surveys from the DB using a query object
	 * 
	 * @param unknown_type $oQuery
	 */
	private function getSurveysFromDB($oQuery, $bAsArray) {
        $mongo = new Mongo();
		Morph_Storage::init($mongo->selectDB('befragungssystem'));
		
		try {
			$oSurvey = new Survey();
			$resultSet = $oSurvey->findByQuery($oQuery);
			
			$aoSurveys = array();
			foreach($resultSet as $oSurvey) {
				if($bAsArray)
			    	$aoSurveys[] = $oSurvey->__toArray();
			    else
			    	$aoSurveys[] = $oSurvey;
			}			
			
			if(sizeof($aoSurveys) > 0)
				return $aoSurveys;
			else
				throw new Morph_Exception_ObjectNotFound();
		} catch(Exception $e) {
			throw $e;
		}
	}
	
	/**
	 * Loads a specific survey from the DB using an ID
	 * 
	 * @param unknown_type $sID
	 */
	private function getSurveyFromDB($oUser, $sID, $bAsArray) {
        $mongo = new Mongo();
		Morph_Storage::init($mongo->selectDB('befragungssystem'));
		
		try {
			$oSurvey = new Survey();
			$oSurvey = $oSurvey->loadByID($sID);
			
			if($bAsArray)
				return $oSurvey->__toArray();
			else
				return $oSurvey;
		} catch(Exception $e) {
			if($e instanceof Morph_ObjectNotFoundException) {
				throw new Exception("Befragung konnte nicht gefunden werden");
			}
		}
	}
	
	/**
	 * Checks if all survey data is set by the user and if it is plausible
	 * 
	 * @param unknown_type $asParams
	 */
	private function isSurveyDataPlausible($asParams) {
		if($asParams['archive'] == "on") {
			return true;
		} else {
			if($asParams['title'] != ""
				&& $asParams['numberOfParticipants'] != ""
				&& $asParams['questionnaireTitle'] != ""
				&& $asParams['validFrom'] != ""
				&& $asParams['validTo'] != "") {
					
				if(strtotime($asParams['validFrom']) > strtotime($asParams['validTo'])) {
					throw new SurveysException("Start- und Enddatum sind ungültig");
				}
				
				if($asParams['periodic'] == "on") {
					if($asParams['period'] == ""
						|| ! is_numeric($asParams['period'])) {
						throw new SurveysException("Geben Sie eine gültige Periodendauer an");
					}
					
					if($asParams['periodUnit'] == ""
						|| ! in_array($asParams['periodUnit'], array("tage", "wochen", "monate"))) {
						throw new SurveysException("Geben Sie eine gültige Periodeneinheit an");
					}
				}
				
				if(! is_numeric($asParams['numberOfParticipants']))
					throw new SurveysException("Geben Sie eine gültige maximale Anzahl an Teilnehmern an");
				
				return true; // no errors
			} else {
				throw new SurveysException("Die Daten sind unvollständig");
			}
		}
	}
	
	/**
	 * Sets the survey data
	 * 
	 * Mapping method: This method evaluates all request parameters relevant to survey data 
	 * 
	 * @param unknown_type $asParams
	 */
	private function setSurveyData($oSurvey, $asParams) {
		try {
			if($oSurvey->isEditable() ||
				(! $oSurvey->isEditable() && $asParams['archive'] != "on")) { // unarchived surveys are editable
				if($asParams['archive'] == "on") { // archive
					$oSurvey->status = 'archived';
				} else {
					if($this->isTitleAvailable($oSurvey, $asParams['title']))
						$oSurvey->title = $asParams['title'];
					$oSurvey->creator = $asParams['creator'];
					$oSurvey->description = $asParams['description'];
					$oSurvey->validFrom = $asParams['validFrom'];
					$oSurvey->validTo = $asParams['validTo'];
					$oSurvey->numberOfParticipants = $asParams['numberOfParticipants'];
					$oSurvey->numberOfParticipations = $asParams['numberOfParticipations'];
					
					if($asParams['periodic'] == "on") {
						$oSurvey->periodic = true;
						$oSurvey->period = $asParams['period'];
						$oSurvey->periodUnit = $asParams['periodUnit'];
					} else {
						$oSurvey->periodic = false;
						$oSurvey->period = "";
						$oSurvey->periodUnit = "";
					}
					
					$oSurvey->isPrivate = $asParams['isPrivate'] == "on";
					
					// questionnaire
					if($oSurvey->questionnaireID) {
						if($asParams['questionnaireTitle'] != $oSurvey->questionnaireID->id()) {
						    $oSurvey->questionnaireID->delete();
							
							// copy new questionnaire
							require_once('model/QuestionnairesManager.php');
							$oQuestionnairesManager = new QuestionnairesManager();
							$oQuestionnaire = $oQuestionnairesManager->makeActiveQuestionnaire($asParams['questionnaireTitle']);
							$oSurvey->questionnaireID = $oQuestionnaire;
						}				
					} else {
						// copy new questionnaire
						require_once('model/QuestionnairesManager.php');
						$oQuestionnairesManager = new QuestionnairesManager();
						$oQuestionnaire = $oQuestionnairesManager->makeActiveQuestionnaire($asParams['questionnaireTitle']);
						$oSurvey->questionnaireID = $oQuestionnaire;
					}
					
					// generate keys
					$oSurvey->withKeys = $asParams['withKeys'] == "on";
					if($oSurvey->withKeys) {
						for($i = 0; $i < $oSurvey->numberOfParticipants; $i++) {
							$oSurvey->keys[] = $this->generateKey();
						}
					}
					
					// 2 stop || ! 2 stop
					if($asParams['stop'] == "on") { // stop survey
						$oSurvey->status = "stopped";
					} else {						
						$oSurvey->adjustStatus(); // adjust status based on dates
					}
				}
			} else { // survey is not editable
				if($oSurvey->status == "active" && $asParams['archive'] == "on") {
					$oSurvey->status = 'archived';
				} else if($oSurvey->status == "active" && $asParams['stop'] == "on") {
					$oSurvey->status = 'stopped';
				} else if($oSurvey->status == "archived" && $asParams['archive'] != "on") {
					$oSurvey->adjustStatus();
				}
			}
			return $oSurvey;
		} catch(Exception $e) {
			throw $e;
		}
	}
			
	/**
	 * Generates a random string
	 * 
	 * code from: http://www.noobis.de/developer/141-php-random-string-erzeugen.html
	 * 
	 * @param unknown_type $length
	 */
	private function generateKey($length = 6) {
		// $chars - String aller erlaubten Zahlen
		$chars = "!abcdefghijklmnopqrstuvwxyz
	            ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
		// Funktionsstart
		srand((double)microtime()*1000000);
		$i = 0; // Counter auf null
		while ($i < $length) { // Schleife solange $i kleiner $length
			// Holen eines zufälligen Zeichens
			$num = rand() % strlen($chars);
			// Ausf&uuml;hren von substr zum wählen eines Zeichens
			$tmp = substr($chars, $num, 1);
			// Anhängen des Zeichens
			$pass = $pass . $tmp;
			// $i++ um den Counter um eins zu erhöhen
			$i++;
		}
		// Schleife wird beendet und
		// $pass (Zufallsstring) zurück gegeben
		return $pass;
	}
	
	/**
	 * Check if a title is taken by a survey with an ID different from
	 * $sSurveyID.
	 * 
	 * @param unknown_type $sSurveyID
	 * @param unknown_type $sUsername
	 * 
	 * @return true title is not taken by another survey
	 *         false title is taken by another survey
	 */
	private function isTitleAvailable($oSurvey, $sTitle) {
		$oQuery = new Morph_Query();
		$oQuery->property('title')->equals($sTitle)
			   ->property('_id')->notEqualTo($oSurvey->id());
		
		try {
			$this->getSurveysFromDB($oQuery, false);
			throw new SurveysException("Dieser Befragungstitel ist bereits vergeben");
		} catch(Morph_Exception_ObjectNotFound $e) {
			return true;
		} catch(SurveysException $e) {
			throw $e;
		}
	}
}
?>
